
function deepClone(origin, hashMap = new WeakMap()) {
  if (origin == undefined || typeof origin !== 'object') return origin;

  if (origin instanceof Date) return new Date(origin);

  if (origin instanceof RegExp) return new RegExp(origin);

  const hashKey = hashMap.get(origin);

  if (hashKey) return hashKey;

  const target = new origin.constructor();

  hashMap.set(origin, target);

  for (const k in origin) {
    if (Object.hasOwnProperty.call(origin, k)) {
      target[k] = deepClone(origin[k], hashMap);
    }
  }

  return target;
}


Array.prototype.myForEach = function (cb) {
  var _arr = this,
      _len = _arr.length,
      _arg2 = arguments[1] || window;

  for (var i = 0; i < _len; i ++) {
    cb.apply(_arg2, [_arr[i], i, _arr]);
  }
}


Array.prototype.myMap = function (cb) {
  var _arr = this,
      _len = _arr.length,
      _arg2 = arguments[1] || window,
      _newArr = [],
      _res,
      _item;

  for (var i = 0; i < _len; i ++) {
    _item = deepClone(_arr[i]);
    _res = cb.apply(_arg2, [_item, i, _arr]);
    _res && _newArr.push(_res);
  }

  return _newArr;
}


Array.prototype.myFilter = function (cb) {
  var _arr = this,
      _len = _arr.length,
      _arg2 = arguments[1] || window,
      _newArr = [],
      _item;

  for (var i = 0; i < _len; i ++) {
    _item = deepClone(_arr[i]);
    cb.apply(_arg2, [_item, i, _arr]) ? _newArr.push(_item) : '';
  }

  return _newArr;
}

Array.prototype.myEvery = function (cb) {
  var _arr = this,
      _len = _arr.length,
      _arg2 = arguments[1] || window,
      _res = true;

  for (var i = 0; i < _len; i ++) {
    if (!cb.apply(_arg2, [_arr[i], i, _arr])) {
      _res = false;
      break;
    }
  }

  return _res;
}


Array.prototype.mySome = function (cb) {
  var _arr = this,
      _len = _arr.length,
      _arg2 = arguments[1] || window,
      _res = false;

  for (var i = 0; i < _len; i ++) {
    if (cb.apply(_arg2, [_arr[i], i, _arr])) {
      _res = true;
      break;
    }
  }
  
  return _res;
}


Array.prototype.myReduce = function (cb, initialValue) {
  var _arr = this,
      _len = _arr.length,
      _arg3 = arguments[2] || window,
      _item;

  for (var i = 0; i < _len; i ++) {
    _item = deepClone(_arr[i]);
    initialValue = cb.apply(_arg3, [initialValue, _item, i, _arr]);
  }

  return initialValue;
}


Array.prototype.myReduceRight = function (cb, initialValue) {
  var _arr = this,
      _len = _arr.length,
      _arg3 = arguments[2] || window,
      _item;

  for (var i = _len; i >= 0; i --) {
    _item = deepClone(_arr[i]);
    initialValue = cb.apply(_arg3, [initialValue, _item, i, _arr]);
  }

  return initialValue;
}